#include "exprDict.h"

///////////////////////////////////////////////////////////////////////////
// TExprXmlhandler ////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
class TExprXmlhandler : public QXmlDefaultHandler 
{ 
public: 
	TExprXmlhandler( QMap <QString, TExpression> *exprMp );
	//
	bool startElement(	const QString &namespaceURI, 
						const QString &localName, 
						const QString &qName, 
						const QXmlAttributes &attribs);
	bool endElement  (  const QString & namespaceURI
					  , const QString & localName
					  , const QString & qName );
private:
	TExpression curExpr;
	QMap <QString, TExpression> *exprMap;
};

///////////////////////////////
//
TExprXmlhandler::TExprXmlhandler( QMap <QString, TExpression> *exprMp )
: exprMap(exprMp)
{}

//
bool TExprXmlhandler::startElement(	const QString &, const QString &, 
									const QString &qName, 
									const QXmlAttributes &attribs) 
{
	if( qName == "expression" ){
		curExpr.name		= attribs.value("name");
		curExpr.expression	= attribs.value("string");
		curExpr.description	= attribs.value("description");
	}
	else
	if( qName == "arg" ){
		TArgument arg;
		if( attribs.value("type") == "tag" ){
			arg.value = attribs.value("id").toUInt(NULL,16);
			QString sPrec = attribs.value("precision");
			if( sPrec.isEmpty() )
				arg.precision = -2;
			else
				arg.precision = sPrec.toInt();
			curExpr.args << arg;
		}
		else
		if( attribs.value("type") == "exp" ){
			arg.value = attribs.value("id");
			curExpr.args << arg;
		}
	}
	return true; 
}

//
bool TExprXmlhandler::endElement( const QString &, const QString &, const QString &qName ) 
{
	if( qName == "expression" ){
		exprMap->insert( curExpr.name, curExpr );
		curExpr.args.clear();
	}
	return true; 
}

///////////////////////////////////////////////////////////////////////////
// TExpression ////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
void TExpression::clear()
{
	name = "";
	expression = "";
	args.clear();
}

///////////////////////////////////////////////////////////////////////////
// TExpressionDict ////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//TEMPORARY
//
TExpressionDict *TExpressionDict::getDict()
{
	static TExpressionDict instance;
	return &instance;
}

//
bool TExpressionDict::loadDict( QString path )
{
	QFile file( path );
	file.open( QIODevice::ReadOnly );
	
	QXmlSimpleReader reader;
	TExprXmlhandler handler( &exprMap );
	
	reader.setContentHandler( &handler );
	reader.parse( &file );

	return true;
}

bool TExpressionDict::saveDict( QString path )
{
	QFile outF( path );
	outF.open( QIODevice::WriteOnly );

	QTextStream out( &outF ); 

	out	<< "<?xml version=\"1.0\" encoding=\"cp-1251\"?>\n"; 
	out	<< "<expressions>\n"; 
	
	QMap<QString,TExpression>::const_iterator it_expr = exprMap.constBegin();
	while (it_expr != exprMap.constEnd() ){
		TExpression expr = it_expr.value();
		out << "\t<expression name=\""	<< expr.name
			<< "\" string=\""			<< expr.expression 
			<< "\" description=\""		<< expr.description
			<< "\">\n";
		foreach(TArgument arg, expr.args ){
			QString argv, type;
			if( arg.value.type() == QVariant::UInt ){
				argv = QString("%1").arg( arg.value.toUInt(), 8, 16, QChar('0') );
				type = "tag";
			}
			else{
				argv = arg.value.toString();
				type = "exp";
			}
			out << "\t\t<arg type=\"" + type + "\"" + " id=\"" + argv + "\"";
			if( arg.precision != -2 )
				out << " precision=\"" + QString::number(arg.precision) + "\"";
			out << "/>\n";
		}
		out << "\t</expression>\n";			
	
		++it_expr;
	}

	out	<< "</expressions>\n";
	return true;
}

//
TExpression TExpressionDict::exprVar(QString name)
{
	return exprMap[name];
}

//
QStringList TExpressionDict::exprNames()
{
	return exprMap.keys();
}

//
bool TExpressionDict::hasExpr( const QString &name ) const
{
	return exprMap.contains(name);
}

//
void TExpressionDict::deleteExpr( QString name )
{
	exprMap.remove( name );
}

//
void TExpressionDict::updateExpr( QString name, TExpression newV )
{
	if( exprMap.contains(name) )
		exprMap.remove( name );
	exprMap[newV.name] = newV;
}